##############################################################################
# yq - Command-line YAML/JSON/XML/Properties/CSV/TSV Processor 速查表
# (Focusing on the Go version by Mike Farah - https://github.com/mikefarah/yq)
# 一个用于查询、修改和转换结构化数据的便携式命令行工具。
# https://github.com/funnyzak/cli-cheatsheets
##############################################################################

# 图例 (Legend):
#   <expression>: yq 路径/操作表达式 (e.g., '.a.b', '.items[0].name', '.[] | select(.enabled == true)')
#   <file>:       输入文件名 (省略时从 stdin 读取)
#   <value>:      要设置或添加的值 (可以是简单值或 YAML/JSON 结构)
#   <format>:     输出格式 (yaml, json, props, csv, tsv, xml)
#   <update_expr>: 更新表达式 (e.g., '.a.b = "new"', '.items.[0].enabled = false', 'del(.old.key)')
#   <merge_expr>:  用于合并的表达式 (e.g., '*=""', '.a * B.a')

##############################################################################
# 读取/选择数据 (Read / Select Data)
##############################################################################

yq <expression> <file>             # 从文件中读取/选择数据 (默认输出 YAML)
cat <file> | yq <expression>       # 从 stdin 读取/选择数据
yq '.a.b' config.yaml              # 获取 key 'b' under 'a' 的值
yq '.items[0]' data.json           # 获取数组 'items' 的第一个元素
yq '.items.[].name' data.yaml      # 获取 'items' 数组中所有元素的 'name' 字段
yq '.items | length' data.yaml     # 获取 'items' 数组的长度
yq 'keys | .[]' config.yaml        # 列出顶层的所有 key
yq '.[] | select(.enabled == true)' services.yaml # 选择 'enabled' 为 true 的所有顶层元素
yq '.a == "value"' config.yaml     # 检查 '.a' 是否等于 "value" (返回 true/false)
yq '.a.b // "default"' config.yaml # 如果 '.a.b' 不存在或为 null，则返回 "default"

##############################################################################
# 修改数据 (Modify Data)
# 注意: 默认输出到 stdout。使用 -i 进行原地修改。
##############################################################################

yq '<update_expr>' <file>          # 修改数据并输出到 stdout
yq -i '<update_expr>' <file>       # 原地修改文件

# 更新值 (Update Values)
yq '.a.b = "new value"' <file>     # 更新 '.a.b' 的值
yq '.a.b |= "new value"' <file>    # 同上 (|= 是赋值操作符)
yq '.items[0].enabled = false' <file> # 更新数组元素的值
yq '.items |= map(select(.age > 30))' <file> # 过滤数组，只保留 age > 30 的元素 (原地修改数组)
yq '.version |= sub("v", "")' <file> # 使用 sub 函数修改字符串

# 添加值 (Add Values)
yq '.a.new_key = "hello"' <file>   # 添加新 key '.a.new_key'
yq '.items += {"name": "new", "val": 1}' <file> # 向数组 'items' 追加元素
yq '.metadata.labels = {"app": "myapp"}' <file> # 添加一个新对象

# 删除值 (Delete Values)
yq 'del(.a.old_key)' <file>        # 删除 key '.a.old_key'
yq 'del(.items[1])' <file>         # 删除数组的第二个元素

##############################################################################
# 创建数据 (Create Data)
##############################################################################

yq -n '.a.b = "value"'             # 创建一个新 YAML/JSON，包含指定结构
yq -n '.items[0].name = "one"'     # 创建包含数组的新文档
yq -n '.a = {"b": 1, "c": [2, 3]}' # 创建复杂结构

##############################################################################
# 格式转换 (Format Conversion)
##############################################################################

yq -o=<format> <file>              # 将文件转换为指定格式输出
yq -o=json config.yaml             # 将 YAML 转换为 JSON
yq -o=yaml data.json               # 将 JSON 转换为 YAML
yq -p=<input_format> -o=<output_format> <file> # 指定输入和输出格式
yq -p=props -o=yaml config.properties # Properties 转 YAML
yq -p=xml -o=json data.xml         # XML 转 JSON
yq -j <file>                       # 快捷方式：输出紧凑 JSON (等效 -o=json -N)

##############################################################################
# 合并文件 (Merge Files)
##############################################################################

yq eval-all '<merge_expr>' file1.yaml file2.yaml ... # 合并多个文件
yq ea '. as $item ireduce ({}; . * $item )' *.yaml # 递归深度合并目录下所有 yaml (常用)
yq 'load("file2.yaml") * .' file1.yaml # 将 file2 合并到 file1 (file1 中的值优先)
yq '. * load("file2.yaml")' file1.yaml # 将 file2 合并到 file1 (file2 中的值优先)
yq ea --inplace '.a = "newValue"' *.yaml # 对多个文件进行相同的原地修改

# 注意: `ea` 是 `eval-all` 的缩写。

##############################################################################
# 处理多文档流 (Multiple Documents)
##############################################################################

yq <expression> multi-doc.yaml     # 默认对所有文档执行表达式
yq 'select(document_index == 0)' multi-doc.yaml # 选择第一个文档
yq 'select(document_index > 0)' multi-doc.yaml # 选择除第一个外的所有文档
yq -d 1 <expression> <file>        # (或 --doc 1) 只处理第二个文档 (索引从 0 开始)
yq eval-all 'select(document_index == 1) | .name = "new"' multi-doc.yaml # 修改第二个文档的 name
yq ---                             # 在输出中手动插入文档分隔符
yq -N                              # 输出时不打印文档分隔符 '---'
yq -s '<expression>' <files...>    # (v4.18+ 已弃用，请用 eval-all) 将多文件/文档读入数组处理

##############################################################################
# 常用选项 (Common Options)
##############################################################################

yq -i, --inplace                 # 原地修改文件
yq -o, --output-format <format>  # 指定输出格式 (yaml, json, props, csv, tsv, xml)
yq -p, --input-format <format>   # 指定输入格式 (同上)
yq -n, --null-input              # 创建新文档，不读取输入
yq -e, --exit-status             # 如果没有匹配结果或结果为 false/null，则以非零状态退出
yq -C, --colors                  # 强制彩色输出
yq -M, --no-colors               # 禁用彩色输出
yq -N, --no-doc-separator        # 不输出 '---' 文档分隔符
yq -r, --raw-output              # 输出原始标量字符串 (无引号，对数字/布尔值无效)
yq -j, --tojson                  # 快捷方式：输出紧凑 JSON (等效于 -o=json -N)
yq -P, --prettyPrint             # 美化输出 (YAML 默认美化，对 JSON 等有用)
yq --indent <num>                # 设置缩进空格数 (默认 2)
yq -v, --verbose                 # 显示详细处理信息 (用于调试表达式)
yq -I<num>, --indentation=<num>  # (旧版?) 同 --indent
yq -S, --sort-keys               # 输出时对 Map 的 Key 进行排序
yq --version                     # 显示 yq 版本

##############################################################################
# 实用技巧 (Tips and Tricks)
##############################################################################

# - 引用: Shell 会解释特殊字符 ($ ' " ` *)。将 yq 表达式用单引号 (') 包裹通常最安全。
# - 复杂值: 设置复杂值 (对象/数组) 时，使用 YAML/JSON 语法:
#   yq -i '.a.new_obj = {"key": "val", "arr": [1, 2]}' file.yaml
#   yq -i '.a.new_list = ["one", "two"]' file.yaml
# - 环境变量: 使用 `env()` 函数读取环境变量:
#   yq '.image.tag = env(TAG)' deployment.yaml
#   TAG=v1.2 yq '.image.tag = env(TAG)' deployment.yaml
# - 结合 Shell:
#   VALUE=$(yq '.a.b' config.yaml)
#   if yq -e '.enabled == true' config.yaml; then ...; fi
# - 更新并读取: yq '.a.b = "new" | .a.b' file.yaml # 更新并立即读取新值
# - 注释保留: yq 默认会尽量保留注释。

##############################################################################
# 示例 (Examples)
##############################################################################

# 假设 config.yaml 内容:
# apiVersion: v1
# kind: Pod
# metadata:
#   name: myapp # Pod 名称
# spec:
#   containers:
#     - name: main
#       image: nginx:latest

# 1. 读取容器镜像 (原始字符串输出):
#   yq -r '.spec.containers[0].image' config.yaml
#   # 输出: nginx:latest

# 2. 原地更新镜像标签 (使用环境变量):
#   export NEW_TAG=1.21-alpine
#   yq -i '.spec.containers[0].image = "nginx:" + env(NEW_TAG)' config.yaml
#   # config.yaml 文件被修改

# 3. 添加一个标签到 metadata:
#   yq -i '.metadata.labels.app = "my-app"' config.yaml

# 4. 将 YAML 转换为紧凑 JSON 并输出:
#   yq -j config.yaml

# 5. 合并 base.yaml 和 overlay.yaml (overlay 优先) 到新文件:
#   yq eval-all '. as $item ireduce ({}; . * $item )' base.yaml overlay.yaml > final.yaml

# 6. 删除所有注释:
#   yq '... comments=""' config.yaml

##############################################################################
# 更多资源 (Further Resources)
##############################################################################

# 官方文档 (Mike Farah's yq): https://mikefarah.gitbook.io/yq/
# GitHub 仓库: https://github.com/mikefarah/yq
# 表达式操作符参考: https://mikefarah.gitbook.io/yq/operators
# 注意: 存在另一个 Python 版本的 yq (kislyuk/yq)，其语法类似 jq，与此速查表不同。

# vim: set ts=4 sw=4 tw=0 et ft=bash :
